<template>
  <div ref="editor" class="monaco-editor">
  </div>
</template>

<script>
import * as monaco from 'monaco-editor'
import createSqlCompleter from './util/sql-completion'
import createJavascriptCompleter from './util/javascript-completion'
import registerLanguage from './util/log-language'

const global = {}
const getHints = model => {
  const id = model.id.substring(6);
  return (global[id] && global[id].hints) || [];
}
monaco.languages.registerCompletionItemProvider(
  'sql',
  createSqlCompleter(getHints)
)
// monaco.languages.registerCompletionItemProvider(
//   'javascript',
//   createJavascriptCompleter(getHints)
// )
registerLanguage(monaco)


export default {
  name: 'monaco-editor',
  cnName: 'monaco-editor',
  props: {
    options: {
      type: Object,
      default() {
        return {};
      }
    },
    value: {
      type: String,
      required: false
    },
    language: {
      type: String
    },
    hints: {
      type: Array,
      default() {
        return [];
      }
    }
  },
  data() {
    return {
      editorInstance: null,
      defaultOptions: {
        theme: 'vs-dark',
        fontSize: 14
      }
    }
  },
  watch: {
    value() {
      if (this.editorInstance && this.value !== this.editorInstance.getValue()) {
        this.editorInstance.setValue(this.value)
      }
    }
  },
  methods: {
    layout() {
      this.editorInstance.layout();
    },
    undo() {
      this.editorInstance.trigger('anyString', 'undo');
      this.onValueChange();
    },
    redo() {
      this.editorInstance.trigger('anyString', 'redo');
      this.onValueChange();
    },
    getOptions() {
      const props = { value: this.value };
      this.language !== undefined && (props.language = this.language);
      const options = Object.assign({}, this.defaultOptions, this.options, props);
      return options;
    },
    onValueChange() {
      this.$emit('input', this.editorInstance.getValue());
      this.$emit('change', this.editorInstance.getValue());
    },
    initEditor() {
      this.editorInstance = monaco.editor.create(
        this.$refs.editor,
        this.getOptions()
      );
      this.editorInstance.onContextMenu(e => {
        this.$emit('contextmenu', e);
      });
      this.editorInstance.onDidChangeModelContent(() => {
        this.onValueChange();
      });
      this.editorInstance.addCommand(
        monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S,
        () => {
          this.$emit('save', this.editorInstance.getValue());
        }
      );

      setTimeout(_ => {
        this.layout()
      }, 150)
    }
  },
  mounted() {
    this.$nextTick(_ => {
      this.initEditor()
      global[this.editorInstance._id] = this
      window.addEventListener('resize', this.layout)
    })
  },
  destroyed() {
    this.editorInstance.dispose()
    global[this.editorInstance._id] = null
    window.removeEventListener('resize', this.layout)
  }
}
</script>

<style lang="less" scoped>
.monaco-editor {
  /deep/ .view-lines * {
    font-family: Consolas, "Courier New", monospace !important;
  }
}
</style>
